var request = require("./request");
var _ = require("underscore");

/* for store cookies */
var j = request.jar();
var jarArray = [];
var cachedData = [];
var scope = {};
var imports = {};

/**
 * @param : request option, cookie string(a=b), cookie scope
 * */
var addCookie = function (next, cookie, uri) {
    var use = false;
    _.each(jarArray, function (obj) {
        if (obj.key == cookie.split("=")[0]) {
            use = true;
            obj.value = cookie.split("=")[1];
        }
    });
    if (!use) {
        jarArray.push({
            key: cookie.split("=")[0],
            value: cookie.split("=")[1],
            uri: uri
        });
    }

    j = request.jar();
    _.each(jarArray, function (obj) {
        j.setCookie(request.cookie(obj.key + "=" + obj.value), obj.uri);
    });
    if (!!next) {
        next.option.jar = j;
    }
};

exports.cacheData = function(res){
    cachedData.push({header : res.headers,body : res.body});
    console.log("Crawler : crawling "+ scope.count + " times");
};
exports.flushData = function(){
    function callbackJudge(cachedData){
        if( typeof scope.analyzer === 'function') {
            scope.analyzer(cachedData);
        } else {
            scope.analyzer.analyseProcess(cachedData);
        }
        cachedData = [];
    }
    scope.dataBuilder.call(imports,cachedData,jarArray,callbackJudge);
};

/**
 * @description : domain function, to start a request chain.
 * */
var startChain = function (current) {
    if(!current.url || !current.method) {
       console.log("Crawler : request param error..");
    }
    current.method = current.method.toUpperCase();
    current.option.method = current.method;

    request(current.url, current.option, function (err, res, body) {
        //current.filter(err,res,body,current.next);
        if(err){
            console.log("Crawler : http request error..");
            console.log(err);
            return;
        }
        current.filter.apply(imports,[err,res,body,current.next]);
        //try catch for stability todo
        if(!!current.next.option)
            setCookie(res.headers, current.next);
        if (!!current.next) {
            if(!current.next.url && !!current.next.filter) {
                /* not filter exactly, it's analyzer, just execute it */
                current.next.filter(err, res);
                return;
            }
            setTimeout(startChain,(Math.random()*(scope.maxReq - scope.minReq) + scope.minReq),current.next);
        }
    });
};

/**
 *  @description : domain function, set cookie from last request automatic
 * */
var setCookie = function (header, next) {
    if (!!next) {
        _.each(header['set-cookie'], function (cookies) {
            _.each(cookies.split(";"), function (obj) {
                if ((obj.split("=")[0] == " Path") || (obj.split("=")[0] == "Path")) {
                    next.url.match(/(.+:\/\/[\d|\w|.|-]*:?\d*)/);
                    var host = RegExp.$1;

                    var uri = host + obj.split("=")[1].replace(";", "");

                    var use = false;
                    _.each(jarArray, function (obj) {
                        if (obj.key == cookies.split(";")[0].split("=")[0]) {
                            use = true;
                            obj.value = cookies.split(";")[0].split("=")[1];
                        }
                    });
                    if (!use) {
                        jarArray.push({
                            key: cookies.split(";")[0].split("=")[0],
                            value: cookies.split(";")[0].split("=")[1],
                            uri: uri
                        });
                    }
                }
            });
        });
        j = request.jar();
        _.each(jarArray, function (obj) {
            j.setCookie(request.cookie(obj.key + "=" + obj.value), obj.uri);
        });
        next.option.jar = j;
    }
};

/**
 *  cookie array
 * */
exports.cookies = jarArray;

/**
 *  start request chain from current option
 *  @param: request option
 * */
exports.startChain = startChain;


/**
 *  setCookie from response header
 *  @param: response headers, next option variable
 * */
exports.setCookie = setCookie;

/**
 * add certain customized cookie
 * @param : next request option, cookie like (a=b), scope uri
 * */
exports.addCookie = addCookie;

/**
 *  @description : original crawler scope, ioc should be done manually
 * */
exports.injectScope = function(obj) {
    scope = obj;
};

/**
 *  @description : ioc, for apply to certain scope
 * */
exports.injectImports = function(obj) {
    imports = obj;
    imports.addCookie = addCookie;
    imports.request = request;
};